const crypto = require('crypto-js')
// 这里主要是因为我使用 js-base64 库会出问题, 如果你的不会则不需要此段代码,可以直接使用js-base64的库
// const base64 = require('js-base64')
const base64 = require('./base64s')

// 获取STS参数信息的接口地址
import http from "@/common/service/service.js";

// 本地缓存数据的key
const cacheKey = "oss-token";
// 本地数据有效期
const validtimes = 1000 * 100;

/**
 * 上传文件
 * @param fileobj
 * @returns {Promise<unknown>}
 */
export function uploadFile(fileobj, fileType = 'image') {
    const filename = fileobj.tempFiles[0].name;
    const filepath = fileobj.tempFilePaths[0];
    return new Promise((resolve, reject) => {
        getFormData(filename).then(data => {
			console.log("上传信息",data)
            uni.uploadFile({
                //后台返回的阿里云存储的上传地址
                url: data.host,
                filePath: filepath,
                fileType,
                name: 'file',
                formData: data.formdata,
                success: res => {
                    uni.hideLoading();
                    uni.showToast({title: '上传成功', icon: 'success', duration: 2000});
                    resolve(data.host +"/"+ data.formdata.key);
                },
                fail: err => {
                    reject(err)
                    uni.hideLoading();
                    uni.showModal({
                        content: err.errMsg,
                        showCancel: false
                    });
                }
            });
        })
    })
}

/**
 * 获取上传文件需要的formdata数据
 */
const getFormData = (filename) => {
    // 先从本地获取token
    return new Promise((resolve => {
        getToken().then(res => {
            // 获取到的token为
            console.log('获取到的token为', res)
            const ossAccessKeyId = res.accessKeyId;
            const securityToken = res.securityToken;
            // 这里遇到过坑, 上传文件的路径一定是bucket域名
            const aliyunServerURL = 'https://' + res.bucket + '.' + "oss-cn-shanghai.aliyuncs.com";
            const policy = getPolicyBase64(5, 150)
            const signature = computeSignature(res.accessKeySecret, policy);
            const aliyunFileKey = getOssPath(filename)

            const formdata = {
                //文件名
                key: aliyunFileKey,
                //后台获取超时时间
                policy: policy,
                //后台获取临时ID
                OSSAccessKeyId: ossAccessKeyId,
                // 如果是STS的话这里的参数必须要
                'x-oss-security-token': securityToken,
                //让服务端返回200,不然，默认会返回204
                success_action_status: '200',
                //后台获取签名
                signature: signature
            };
            let data = {
                host: aliyunServerURL,
                formdata: formdata
            }
            resolve(data);
        })
    }))
}

/**
 * 获取token信息的方法
 */
const getToken = () => {
    return new Promise((resolve, reject) => {
        // 先从缓存中获取数据
        const tempData = uni.getStorageSync(cacheKey);
        // 是否有效
        let isvalid = false;
        if (tempData && tempData !== '') {
            // 数据存在,判断数据是否过期
            const tokenObj = JSON.parse(tempData);
            // 判断是否过期 (createtime:是后端指点的创建时间字段)
            var diff = new Date().getTime() - Number.parseFloat(tokenObj.createtime);
            // 判断数据是否过期
            isvalid = diff < validtimes;
        }

        if (isvalid) {
            // 数据有效且未过期则使用缓存中的数据
            resolve(JSON.parse(tempData));
        } else {
            // 无有效数据或数据已过期则从新获取数据
            getToken4Api(cacheKey).then(res => {
                resolve(res);
            })
        }
    })
}


/**
 * 从网关获取数据
 * @param cacheKey
 */
const getToken4Api = (cacheKey) => {
    return new Promise((resolve, reject) => {
		
		http.get("/demand/uploadFile",  {type:"image"}).then(res=>{
			// 将数据存到本地存储, 由于token信息是有有效时间的,
			uni.setStorageSync(cacheKey, JSON.stringify(res.data))
			resolve(res.data)
		})
    })
}

/**
 * 设置OSS的存储路径
 * @param filename 文件名称
 * @returns {string}
 */
const getOssPath = (filename) => {
    const current_timestamp = new Date().getTime()
    const upload_name = filename;
    const current_day = dateformat('YYYYmmdd', new Date())
    return current_day + '/' + new Date().getTime()
}

/**
 * 日期格式化方法
 * @param fmt ex: yyyy-MM-dd HH:mm:ss
 * @param date new Date()
 * @returns {*}
 */
const dateformat = (fmt, date) => {
    let ret;
    const opt = {
        "Y+": date.getFullYear().toString(), // 年
        "m+": (date.getMonth() + 1).toString(), // 月
        "d+": date.getDate().toString(), // 日
        "H+": date.getHours().toString(), // 时
        "M+": date.getMinutes().toString(), // 分
        "S+": date.getSeconds().toString() // 秒
        // 有其他格式化字符需求可以继续添加，必须转化成字符串
    };
    for (let k in opt) {
        ret = new RegExp("(" + k + ")").exec(fmt);
        if (ret) {
            fmt = fmt.replace(ret[1], (ret[1].length === 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
        }
    }
    return fmt;
}

/**
 * 安全策略需要转成base64
 * @param timeout 超时时间
 * @param maxsize 文件大小限制
 * @returns {*}
 */
const getPolicyBase64 = function (timeout, maxsize) {
    const date = new Date()
    // 限制参数的生效时间(单位：小时)。
    const timeOut = timeout || 1
    // 限制上传文件大小(单位：MB)。 1MB = 1048576B
    const maxSize = maxsize || 10
    date.setHours(date.getHours() + timeOut)
    const policyText = {
        expiration: date.toISOString(),
        conditions: [
            ['content-length-range', 0, maxSize * 1024 * 1024]
        ]
    }
    // policy必须为base64的string。
    return base64.encode(JSON.stringify(policyText))
}

/**
 * 计算签名
 * @param accessKeySecret
 * @param canonicalString
 * @returns {string}
 */
const computeSignature = function (accessKeySecret, canonicalString) {
    return crypto.enc.Base64.stringify(
        crypto.HmacSHA1(canonicalString, accessKeySecret)
    )
}


module.exports = {
    uploadFile: uploadFile
};


